﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using System.Management;

namespace WatchDog
{
    public partial class MainForm : Form
    {
        #region C'tor
        public MainForm()
        {
            InitializeComponent();
            EnableButtons();
            Watcher.Success += OnSuccess;
            Watcher.Failed += OnFailed;
        }
        #endregion C'tor

        #region Members
        private List<string> ips = new List<string>();
        private bool watching;
        private Watcher watcher;
        private string cellData;
        private string computerName;
        private string ipAddress;
        private string status;
        #endregion Members

        #region Methods
        private void EnableButtons()
        {
            this.startWatchButton.Enabled = this.ips.Count > 0 && !watching;
            this.stopWatchButton.Enabled = watching;
        }

        private void UpdateDataGrid()
        {
            if (this.watcher != null)
            {
                this.watcher.StopWatch();
                this.watching = false;
            }

            this.dataGridView1.Rows.Clear();
            foreach (var ip in this.ips)
            {
                this.dataGridView1.Rows.Add(new object[] { ip, string.Empty, "Unknown" });
            }
        }

        private void OnSuccess(string ip, string hostName)
        {
            var row = GetRowAccordingToIp(ip);
            row.Cells[1].Value = hostName;
            row.Cells[2].Value = "Sucess";
            row.Cells[2].Style.ForeColor = Color.Green;
        }

        private void OnFailed(string ip)
        {
            var row = GetRowAccordingToIp(ip);
            row.Cells[2].Value = "Failed";
            row.Cells[2].Style.ForeColor = Color.Red;
        }

        private DataGridViewRow GetRowAccordingToIp(string ip)
        {
            DataGridViewRow row = this.dataGridView1.Rows
                .Cast<DataGridViewRow>()
                .Where(r => r.Cells[0].Value.ToString().Equals(ip))
                .First();

            return row;
        }

        private void ShutdownOrRestart(string restartOrShutdown)
        {
            try
            {
                ConnectionOptions options = new ConnectionOptions();
                options.EnablePrivileges = true;
                using (var authentication = new Authentication())
                {
                    var result = authentication.ShowDialog();
                    if (result == DialogResult.Cancel) return;
                    // To connect to the remote computer using a different account, specify these values:
                    
                    // options.Username = "USERNAME";
                    options.Username = authentication.UserName;
                    
                    // options.Password = "PASSWORD";
                    options.Password = authentication.Password;
                    
                    // options.Authority = "ntlmdomain:DOMAIN";
                    options.Authority = authentication.Domain;
                }

                ManagementScope scope = new ManagementScope(
                  "\\\\" + computerName + "\\root\\CIMV2", options);
                scope.Connect();

                SelectQuery query = new SelectQuery("Win32_OperatingSystem");
                ManagementObjectSearcher searcher =
                    new ManagementObjectSearcher(scope, query);
                //if i want to reboot change the string to Win32Reboot
                foreach (ManagementObject os in searcher.Get())
                {
                    // Obtain in-parameters for the method
                    ManagementBaseObject inParams =
                        os.GetMethodParameters(restartOrShutdown);

                    // Add the input parameters.
                    inParams["Flags"] = 2;

                    // Execute the method and obtain the return values.
                    ManagementBaseObject outParams =
                        os.InvokeMethod(restartOrShutdown, inParams, null);
                }
            }
            catch (ManagementException err)
            {
                MessageBox.Show("An error occurred while trying to execute the WMI method: " + err.Message);
            }
            catch (System.UnauthorizedAccessException unauthorizedErr)
            {
                MessageBox.Show("Connection error (user name or password might be incorrect): " + unauthorizedErr.Message);
            }
        }
        #endregion Methods

        #region Events
        private void AddRangeButtonClick(object sender, EventArgs e)
        {
            using (var dlg = new AddRange())
            {
                var result = dlg.ShowDialog();
                if (result == DialogResult.Cancel)
                    return;
                this.ips = dlg.IPList;
            }
            UpdateDataGrid();
            EnableButtons();
        }

        private void StartWatchButtonClick(object sender, EventArgs e)
        {
            this.watcher = new Watcher(this.ips);
            this.watching = true;
            EnableButtons();
        }

        private void StopWatchButtonClick(object sender, EventArgs e)
        {
            this.watcher.StopWatch();
            this.watching = false;
            EnableButtons();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.watcher != null)
            {
                this.watcher.StopWatch();
                Thread.Sleep(100);
            }
            Watcher.Success -= OnSuccess;
            Watcher.Failed -= OnFailed;
        }

        private void dataGridView1_MouseClick(object sender, MouseEventArgs e)
        {
            if (!this.stopWatchButton.Enabled) return;
            if (e.Button == MouseButtons.Right)
            {
                int currentMouseOverRow = dataGridView1.HitTest(e.X, e.Y).RowIndex;
                int currentMouseOverCulomn = dataGridView1.HitTest(e.X, e.Y).ColumnIndex;
                cellData = (string)dataGridView1.Rows[currentMouseOverRow].Cells[currentMouseOverCulomn].Value;
                computerName = (string)dataGridView1.Rows[currentMouseOverRow].Cells[1].Value;
                ipAddress = (string)dataGridView1.Rows[currentMouseOverRow].Cells[0].Value;
                status = (string)dataGridView1.Rows[currentMouseOverRow].Cells[2].Value;

                contextMenuStrip1.Show(dataGridView1, new Point(e.X, e.Y));
            }
        }

        private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (e.ClickedItem.Text == "Copy")
            {
                Clipboard.SetText(cellData);
            }
            if (status != "Sucess") return;
            if (e.ClickedItem.Text == "Shut down")
            {
                ShutdownOrRestart("Win32Shutdown");
            }

            if (e.ClickedItem.Text == "Restart")
            {
                ShutdownOrRestart("Win32Reboot");
            }

        }
        #endregion Events

    }
}
